package com.koushikdutta.ion;

import com.koushikdutta.ion.bitmap.Transform;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;

class DefaultTransform implements Transform {
    final ScaleMode scaleMode;
    final int resizeWidth;
    final int resizeHeight;

    public DefaultTransform(int width, int height, ScaleMode scaleMode) {
        resizeWidth = width;
        resizeHeight = height;
        // fixup ScaleMode to sane values.
        // no scale mode means that we are stretching, disregarding aspect ratio
        if (scaleMode == null)
            this.scaleMode = ScaleMode.FitXY;
        else
            this.scaleMode = scaleMode;
    }

    final static Paint bilinearSamplingPaint = new Paint();

    @Override
    public PixelMap transform(PixelMap b) {
        PixelFormat config = b.getImageInfo().pixelFormat;
        if (config == null)
            config = PixelFormat.ARGB_8888;
        int resizeWidth = this.resizeWidth;
        int resizeHeight = this.resizeHeight;
        if (resizeWidth <= 0) {
            float ratio = (float) b.getImageInfo().size.width / (float) b.getImageInfo().size.height;
            resizeWidth = (int) (ratio * resizeHeight);
        } else if (resizeHeight <= 0) {
            float ratio = (float) b.getImageInfo().size.width / (float) b.getImageInfo().size.height;
            resizeHeight = (int) (ratio * resizeWidth);
        }
        Rect destination = new Rect(0, 0, resizeWidth, resizeHeight);
        ScaleMode scaleMode = this.scaleMode;

        if (scaleMode == ScaleMode.CenterInside) {
            // center inside, but bitmap bounds exceed the resize dimensions...
            // so change it to fit center.
            if (resizeWidth <= b.getImageInfo().size.width || resizeHeight <= b.getImageInfo().size.height)
                scaleMode = ScaleMode.FitCenter;
        }

        if (scaleMode == ScaleMode.CenterInside) {
            float marginX = (resizeWidth - b.getImageInfo().size.width) / 2f;
            float marginY = (resizeHeight - b.getImageInfo().size.height) / 2f;
            destination.minX = (int) marginX;
            destination.minY = (int) marginY;
            destination.width = (int) marginX + b.getImageInfo().size.width;
            destination.height = (int) marginY + b.getImageInfo().size.height;
        } else if (scaleMode != ScaleMode.FitXY) {
            float ratio;
            float xratio = (float) resizeWidth / (float) b.getImageInfo().size.width;
            float yratio = (float) resizeHeight / (float) b.getImageInfo().size.height;
            if (scaleMode == ScaleMode.CenterCrop)
                ratio = Math.max(xratio, yratio);
            else
                ratio = Math.min(xratio, yratio);

            if (ratio == 0) return b;

            float postWidth = (float) b.getImageInfo().size.width * ratio;
            float postHeight = (float) b.getImageInfo().size.height * ratio;
            float transx = (resizeWidth - postWidth) / 2;
            float transy = (resizeHeight - postHeight) / 2;

            destination.minX = (int) transx;
            destination.minY = (int) transy;
            destination.width = resizeWidth - (int) transx;
            destination.height = resizeHeight - (int) transy;
        }

        if (destination.width == b.getImageInfo().size.width && destination.height == b.getImageInfo().size.height
                && destination.minX == 0 && destination.minY == 0) {
            return b;
        }

        // 配置PixelMap
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = config;

        PixelMap pixelMap = PixelMap.create(b, initializationOptions);
        PixelMapHolder pixelMapHolder = new PixelMapHolder(pixelMap);
        Canvas canvas = new Canvas();
        canvas.drawPixelMapHolder(pixelMapHolder, destination.minX, destination.minY, bilinearSamplingPaint);
        return pixelMap;
    }

    @Override
    public String key() {
        return scaleMode.name() + resizeWidth + "x" + resizeHeight;
    }
}
